home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / viewkit / VCal / Entry.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  11.7 KB  |  529 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include "Entry.h"
  20. #include "Utils.h"
  21.  
  22. #define PRINT_WIDTH    80
  23. #define PRINT_LEADER    22
  24. #define PRINT_INDENT    2
  25. #define PRINT_MARGIN    2
  26.  
  27. const EntryKindInfo entryKindList[] = {
  28.   { E_single, "Single Instance" },
  29.   { E_repeatDaily, "Each Day" },
  30.   { E_repeatWeekDaily, "Each Weekday" },
  31.   { E_repeatWeekly, "Each Week" },
  32.   { E_repeatBiWeekly, "Every Other Week" },
  33.   { E_repeatMonthlyDate, "Each Month, Same Date" },
  34.   { E_repeatMonthlyDay, "Each Month, Same Weekday" },
  35.   { E_repeatMonthlyDateEnd, "Each Month, Same Days From End" },
  36.   { E_repeatMonthlyDayEnd, "Each Month, Same Weekday From End" },
  37.   { E_repeatYearly, "Each Year" },
  38. };
  39.  
  40. const int entryKindCount = sizeof(entryKindList) / sizeof(EntryKindInfo);
  41.  
  42. Entry::Entry()
  43. {
  44.   _day = 0;
  45.   _month = 0;
  46.   _year = 0;
  47.   _start = 0;
  48.   _length= 0;
  49.  
  50.   _notifyPopup = 1;
  51.   _notifyBell = 1;
  52.   _notifyMail = 0;
  53.   _notifyCommand = strdup("");
  54.  
  55.   _kind = E_single;
  56.   _annotate = 1;
  57.   setAlarmFired(0, ALL_NOTIFICATIONS);
  58.   _next = NULL;
  59.   _next2 = NULL;
  60.   _advance = strdup("");
  61.   _text = strdup("");
  62.   _data = NULL;
  63.   _snoozeData = NULL;
  64.   _alarmInfo = new EntryAlarmInfo;
  65.  
  66.   _alarmInfo->entry = this;
  67.   _alarmInfo->alarm = NULL;
  68.   _alarmInfo->data = NULL;
  69. }
  70.  
  71. Entry::~Entry()
  72. {
  73.   free(_advance);
  74.   free(_text);
  75.   delete _alarmInfo;
  76.   free(_notifyCommand);
  77. }
  78.  
  79. void
  80. Entry::setNotifyCommand(char *v)
  81. {
  82.   free(_notifyCommand);
  83.   _notifyCommand = strdup(v);
  84. }
  85.  
  86. void
  87. Entry::setAlarmFired(int v, int alarmIndex)
  88. {
  89.   int each;
  90.  
  91.   if (alarmIndex != ALL_NOTIFICATIONS) {
  92.     _alarmFired[alarmIndex] = v;
  93.   } else {
  94.     for (each=0; each<MAX_ALARM_NOTIFICATIONS; each++) {
  95.       _alarmFired[each] = v;
  96.     }
  97.   }
  98. }
  99.  
  100.  
  101. int
  102. Entry::setAlarmAdvance(char *str)
  103. {
  104.   char *newstr;
  105.  
  106.   if (newstr = reformatAdvanceString(str)) {
  107.     free(_advance);
  108.     _advance = newstr;
  109.     return 1;
  110.   } else {
  111.     return 0;
  112.   }
  113. }
  114.  
  115. int
  116. Entry::setText(char *t)
  117. {
  118.   free(_text);
  119.   _text = strdup(t);
  120.   return 1;
  121. }
  122.  
  123. int
  124. Entry::alarmApplies(int time, int *alarmIndex, int unfiredOnly)
  125. {
  126.   int mins;
  127.   char *current, *remainder;
  128.  
  129.   current = alarmAdvance();
  130.   *alarmIndex = 0;
  131.   while (current) {
  132.     mins = parseAdvance(current, &remainder);
  133.     if ((!unfiredOnly || !_alarmFired[*alarmIndex]) &&
  134. // This doesn't work across midnight
  135.     mins != -1 && mins < MINS_IN_DAY && start() <= time+mins) {
  136.       return 1;
  137.     }
  138.     current = remainder;
  139.     (*alarmIndex)++;
  140.   }
  141.   if (unfiredOnly) {
  142.     return alarmApplies(time, alarmIndex, 0);
  143.   } else {
  144.     return 0;
  145.   }
  146. }
  147.  
  148. int
  149. Entry::alarmApplies(int d, int m, int y, int *alarmIndex,
  150.             int *matchDay, int *matchMonth, int *matchYear,
  151.             int unfiredOnly)
  152. {
  153.   int mins, days;
  154.   char *current, *remainder;
  155.  
  156.   current = alarmAdvance();
  157.   *alarmIndex = 0;
  158.   while (current) {
  159.     mins = parseAdvance(current, &remainder);
  160.     if ((!unfiredOnly || !_alarmFired[*alarmIndex]) &&
  161.     mins != -1 && mins >= MINS_IN_DAY) {
  162.       days = mins/MINS_IN_DAY;
  163.       if (daysInAdvance(days, d, m, y, matchDay, matchMonth, matchYear)) {
  164.     return 1;
  165.       }
  166.     }
  167.     current = remainder;
  168.     (*alarmIndex)++;
  169.   }
  170.   if (unfiredOnly) {
  171.     return alarmApplies(d, m, y, alarmIndex, matchDay, matchMonth, matchYear,
  172.             0);
  173.   } else {
  174.     return 0;
  175.   }
  176. }
  177.  
  178. void
  179. Entry::setDate(int day, int month, int year)
  180. {
  181.   _day = day;
  182.   _month = month;
  183.   _year = year;
  184. }
  185.  
  186. int
  187. Entry::readEntry(FILE *fd, int version)
  188. {
  189.   int k, v;
  190.   char adv[MAXSTR], str[MAXSTR];
  191.  
  192.   if (!readInt(fd, &_start) ||
  193.       !readInt(fd, &_length) ||
  194.       !readInt(fd, &k)) {
  195.     return 0;
  196.   }
  197.   if (version == 4) {
  198.     if (!readInt(fd, &v)) {
  199.       return 0;
  200.     } else {
  201.       _notifyPopup = _notifyBell = v;
  202.       _notifyMail = 0;
  203.       _notifyCommand = strdup("");
  204.     }
  205.   } else {
  206.     if (!readInt(fd, &_notifyPopup) ||
  207.     !readInt(fd, &_notifyBell) ||
  208.     !readInt(fd, &_notifyMail) ||
  209.     !readStr(fd, str)) {
  210.       return 0;
  211.     } else {
  212.       setNotifyCommand(str);
  213.     }
  214.   }
  215.   if (version == 4) {
  216.     if (!readInt(fd, &v)) {
  217.       return 0;
  218.     } else {
  219.       sprintf(adv, "%d min", v);
  220.     }
  221.   } else {
  222.     if (!readStr(fd, adv)) {
  223.       return 0;
  224.     }
  225.   }
  226.   if (!readInt(fd, &_annotate) ||
  227.       !readStr(fd, str)) {
  228.     return 0;
  229.   } else {
  230.     _kind = (EntryKind) k;
  231.     setAlarmAdvance(adv);
  232.     setText(str);
  233.     return 1;
  234.   }
  235. }
  236.  
  237. void
  238. Entry::writeEntry(FILE *fd, int annotate)
  239. {
  240.   writeInt(fd, _start, annotate ? "Start Time (mins)" : NULL);
  241.   writeInt(fd, _length, annotate ? "Length (mins)" : NULL);
  242.   writeInt(fd, (int) _kind, annotate ? "Repeating Kind" : NULL);
  243.   writeInt(fd, _notifyPopup, annotate ? "Notification Popup?" : NULL);
  244.   writeInt(fd, _notifyBell, annotate ? "Notification Bell?" : NULL);
  245.   writeInt(fd, _notifyMail, annotate ? "Notification Mail?" : NULL);
  246.   writeStr(fd, _notifyCommand);
  247.   writeStr(fd, _advance);
  248.   writeInt(fd, _annotate, annotate ? "Annotate Month View?" : NULL);
  249.   writeStr(fd, _text);
  250. }
  251.  
  252. void
  253. Entry::printEntry(FILE *fd, int clock24)
  254. {
  255.   int hour, min, chars, space;
  256.   char str[MAXSTR], *p, *q;
  257.  
  258.   for (space=0; space<PRINT_MARGIN; space++) {
  259.     fprintf(fd, " ");
  260.   }
  261.   chars = PRINT_MARGIN;
  262.  
  263.   hour = _start/60;
  264.   min = _start % 60;
  265.   formatTime(hour, min, clock24, str);
  266.   fprintf(fd, "%s", str);
  267.   chars += strlen(str);
  268.  
  269.   hour = (_start+_length)/60;
  270.   min = (_start+_length) % 60;
  271.   formatTime(hour, min, clock24, str);
  272.   fprintf(fd, "-%s", str);
  273.   chars += 1+strlen(str);
  274.  
  275.   for (space=chars; space<PRINT_LEADER-PRINT_INDENT; space++) {
  276.     fprintf(fd, " ");
  277.   }
  278.  
  279.   p = _text;
  280.  
  281.   while (strlen(p) > PRINT_WIDTH-PRINT_LEADER) {
  282.     q = strrchr(p+PRINT_WIDTH-PRINT_LEADER, ' ');
  283.     if (!q) {
  284.       q = p+PRINT_WIDTH-PRINT_LEADER;
  285.     }
  286.     while (p <= q) {
  287.       fprintf(fd, "%c", *p);
  288.       p++;
  289.     }
  290.     fprintf(fd, "\n");
  291.     p = q+1;
  292.   }
  293.  
  294.   fputs(_text, fd);
  295.   fprintf(fd, "\n");
  296. }
  297.  
  298. int
  299. Entry::daysInAdvance(int days, int d, int m, int y,
  300.              int *matchDay, int *matchMonth, int *matchYear)
  301. {
  302.   if (compareDates(d, m, y, _day, _month, _year) == 1) {
  303.     // Alarm already happened
  304.     return 0;
  305.   } else {
  306.     augmentDate(d, m, y, days, matchDay, matchMonth, matchYear);
  307.     return (computeDayDifference(_day, _month, _year, d, m, y) == days);
  308.   }
  309. }
  310.  
  311. char *
  312. Entry::reformatAdvanceString(char *str)
  313. {
  314.   char *current, *remain, newstr[MAXSTR];
  315.   int mins;
  316.  
  317.   strcpy(newstr, "");
  318.   current = str;
  319.   while (current &&
  320.      (mins = parseAdvance(current, &remain)) != -1) {
  321.     if (current != str) {
  322.       strcat(newstr, ", ");
  323.     }
  324.     if (mins >= MINS_IN_DAY) {
  325.       sprintf(newstr+strlen(newstr), "%d day", mins/MINS_IN_DAY);
  326.       if (mins/MINS_IN_DAY > 1) {
  327.     strcat(newstr, "s");
  328.       }
  329.     } else if (mins && mins % MINS_IN_HOUR == 0) {
  330.       sprintf(newstr+strlen(newstr), "%d hour", mins/MINS_IN_HOUR);
  331.       if (mins/MINS_IN_HOUR > 1) {
  332.     strcat(newstr, "s");
  333.       }
  334.     } else {
  335.       sprintf(newstr+strlen(newstr), "%d min", mins);
  336.       if (mins > 1) {
  337.     strcat(newstr, "s");
  338.       }
  339.     }
  340.     current = remain;
  341.   }
  342.   if (current) {
  343.     return NULL;
  344.   } else {
  345.     return strdup(newstr);
  346.   }
  347. }
  348.  
  349. int
  350. Entry::parseAdvance(char *str, char **remainder)
  351. {
  352.   int num;
  353.   char *p, *q, old;
  354.  
  355.   while (*str == ' ' || *str == '\t') {
  356.     str++;
  357.   }
  358.   p = str;
  359.   while (*p >= '0' && *p <= '9') {
  360.     p++;
  361.   }
  362.   if (p == str) {
  363.     // No value
  364.     *remainder = NULL;
  365.     return -1;
  366.   }
  367.   old = *p;
  368.   *p = '\0';
  369.   num = atoi(str);
  370.   *p = old;
  371.   while (*p == ' ' || *p == '\t') {
  372.     p++;
  373.   }
  374.   if (*p == ',') {
  375.     *remainder = p+1;
  376.     return num;
  377.   } else if (*p == '\0') {
  378.     *remainder = NULL;
  379.     return num;
  380.   } else {    q = p;
  381.     while (*p != ',' && *p != '\0') {
  382.       p++;
  383.     }
  384.     if (*p == ',') {
  385.       *remainder = p+1;
  386.     } else if (*p == '\0') {
  387.       *remainder = NULL;
  388.     }
  389.     if (!strncasecmp(q, "min", 3)) {
  390.       return num;
  391.     } else if (!strncasecmp(q, "hour", 4)) {
  392.       return num*MINS_IN_HOUR;
  393.     } else if (!strncasecmp(q, "day", 3)) {
  394.       return num*MINS_IN_DAY;
  395.     }
  396.   }
  397.   return -1;
  398. }
  399.  
  400. /**********************************************************************/
  401.  
  402. RepeatingEntry::RepeatingEntry()
  403. {
  404.   _repeatEndDay = 0;
  405.   _repeatEndMonth = 0;
  406.   _repeatEndYear = 0;
  407. }
  408.  
  409. RepeatingEntry::~RepeatingEntry()
  410. {
  411. }
  412.  
  413. int
  414. RepeatingEntry::repeatApplies(int day, int month, int year)
  415. {
  416.   int result, weekday, diff;
  417.  
  418.   if (compareDates(day, month, year, _day, _month, _year) < 0) {
  419.     return 0;
  420.   } else if (_repeatEndDay && _repeatEndMonth && _repeatEndYear &&
  421.          compareDates(day, month, year, _repeatEndDay, _repeatEndMonth,
  422.               _repeatEndYear) > 0) {
  423.     return 0;
  424.   } else {
  425.     result = 0;
  426.     switch (_kind) {
  427.     case E_repeatDaily:
  428.       result = 1;
  429.       break;
  430.     case E_repeatWeekDaily:
  431.       weekday = computeWeekday(day, month, year);
  432.       result = (weekday != 1 && weekday != 7);
  433.       break;
  434.     case E_repeatWeekly:
  435.       weekday = computeWeekday(day, month, year);
  436.       result = (weekday == _weekday);
  437.       break;
  438.     case E_repeatBiWeekly:
  439.       diff = computeDayDifference(day, month, year, _day, _month, _year);
  440.       result = (diff % 14) == 0;
  441.       break;
  442.     case E_repeatMonthlyDate:
  443.       result = (day == _day);
  444.       break;
  445.     case E_repeatMonthlyDay:
  446.       weekday = computeWeekday(day, month, year);
  447.       result = (weekday == _weekday && ((day-1)/7) == ((_day-1)/7));
  448.       break;
  449.     case E_repeatMonthlyDateEnd:
  450.       result = (NumberOfDays(month, year)-day ==
  451.         NumberOfDays(_month, _year)-_day);
  452.       break;
  453.     case E_repeatMonthlyDayEnd:
  454.       weekday = computeWeekday(day, month, year);
  455.       result = (weekday == _weekday &&
  456.         (NumberOfDays(month, year)-day)/7 ==
  457.         (NumberOfDays(_month, _year)-_day)/7);
  458.       break;
  459.     case E_repeatYearly:
  460.       result = (_day == day && _month == month);
  461.       break;
  462.     case E_none:
  463.     case E_single:
  464.     default:
  465.       break;
  466.     }
  467.     return result;
  468.   }
  469. }
  470.  
  471. void
  472. RepeatingEntry::setDate(int day, int month, int year)
  473. {
  474.   Entry::setDate(day, month, year);
  475.   _weekday = computeWeekday(day, month, year);
  476. }
  477.  
  478. int
  479. RepeatingEntry::readEntry(FILE *fd, int version)
  480. {
  481.   if (!Entry::readEntry(fd, version) ||
  482.       !readInt(fd, &_repeatEndDay) ||
  483.       !readInt(fd, &_repeatEndMonth) ||
  484.       !readInt(fd, &_repeatEndYear)) {
  485.     return 0;
  486.   } else {
  487.     return 1;
  488.   }
  489. }
  490.  
  491. void
  492. RepeatingEntry::writeEntry(FILE *fd, int annotate)
  493. {
  494.   Entry::writeEntry(fd, annotate);
  495.   writeInt(fd, _repeatEndDay, annotate ? "Repeat End Day" : NULL);
  496.   writeInt(fd, _repeatEndMonth, annotate ? "Repeat End Month" : NULL);
  497.   writeInt(fd, _repeatEndYear, annotate ? "Repeat End Year" : NULL);
  498. }
  499.  
  500. int
  501. RepeatingEntry::daysInAdvance(int days, int d, int m, int y,
  502.                   int *matchDay, int *matchMonth, int *matchYear)
  503. {
  504.   augmentDate(d, m, y, days, matchDay, matchMonth, matchYear);
  505.   return repeatApplies(*matchDay, *matchMonth, *matchYear);
  506. }
  507.  
  508. int
  509. RepeatingEntry::readDate(FILE *fd, int)
  510. {
  511.   if (!readInt(fd, &_day) ||
  512.       !readInt(fd, &_month) ||
  513.       !readInt(fd, &_year)) {
  514.     return 0;
  515.   } else {
  516. // So that auxiliary computations occur
  517.     setDate(_day, _month, _year);
  518.     return 1;
  519.   }
  520. }
  521.  
  522. void
  523. RepeatingEntry::writeDate(FILE *fd, int annotate)
  524. {
  525.   writeInt(fd, _day, annotate ? "Repeat Start Day" : NULL);
  526.   writeInt(fd, _month, annotate ? "Repeat Start Month" : NULL);
  527.   writeInt(fd, _year, annotate ? "Repeat Start Year" : NULL);
  528. }
  529.